{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "regression.ipynb",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [],
      "toc_visible": true
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.5"
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "FhGuhbZ6M5tl"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "AwOEIRJC6Une",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "KyPEtTqk6VdG",
        "colab": {}
      },
      "source": [
        "#@title MIT License\n",
        "#\n",
        "# Copyright (c) 2017 François Chollet\n",
        "#\n",
        "# Permission is hereby granted, free of charge, to any person obtaining a\n",
        "# copy of this software and associated documentation files (the \"Software\"),\n",
        "# to deal in the Software without restriction, including without limitation\n",
        "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
        "# and/or sell copies of the Software, and to permit persons to whom the\n",
        "# Software is furnished to do so, subject to the following conditions:\n",
        "#\n",
        "# The above copyright notice and this permission notice shall be included in\n",
        "# all copies or substantial portions of the Software.\n",
        "#\n",
        "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
        "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
        "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
        "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
        "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
        "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
        "# DEALINGS IN THE SOFTWARE."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "EIdT9iu_Z4Rb"
      },
      "source": [
        "# 回帰：燃費を予測する "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "bBIlTPscrIT9"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/regression\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />View on TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ja/tutorials/keras/regression.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ja/tutorials/keras/regression.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "tudzcncJXetB"
      },
      "source": [
        "Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳は**ベストエフォート**であるため、この翻訳が正確であることや[英語の公式ドキュメント](https://www.tensorflow.org/?hl=en)の 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリ[tensorflow/docs](https://github.com/tensorflow/docs)にプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [docs-ja@tensorflow.org メーリングリスト](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ja)にご連絡ください。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "AHp3M9ZmrIxj"
      },
      "source": [
        "回帰問題では、価格や確率といった連続的な値の出力を予測することが目的となります。これは、分類問題の目的が、（たとえば、写真にリンゴが写っているかオレンジが写っているかといった）離散的なラベルを予測することであるのとは対照的です。\n",
        "\n",
        "このノートブックでは、古典的な[Auto MPG](https://archive.ics.uci.edu/ml/datasets/auto+mpg)データセットを使用し、1970年代後半から1980年台初めの自動車の燃費を予測するモデルを構築します。この目的のため、モデルにはこの時期の多数の自動車の仕様を読み込ませます。仕様には、気筒数、排気量、馬力、重量などが含まれています。\n",
        "\n",
        "このサンプルでは`tf.keras` APIを使用しています。詳細は[このガイド](https://www.tensorflow.org/guide/keras)を参照してください。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "moB4tpEHxKB3",
        "colab": {}
      },
      "source": [
        "# ペアプロットのためseabornを使用します\n",
        "!pip install seaborn"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "1rRo8oNqZ-Rj",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "import pathlib\n",
        "\n",
        "import matplotlib.pyplot as plt\n",
        "import pandas as pd\n",
        "import seaborn as sns\n",
        "\n",
        "try:\n",
        "  # %tensorflow_version はColab でのみ利用可能\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "    pass\n",
        "import tensorflow as tf\n",
        "\n",
        "from tensorflow import keras\n",
        "from tensorflow.keras import layers\n",
        "\n",
        "print(tf.__version__)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "F_72b0LCNbjx"
      },
      "source": [
        "## Auto MPG データセット\n",
        "\n",
        "このデータセットは[UCI Machine Learning Repository](https://archive.ics.uci.edu/ml/)から入手可能です。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "gFh9ne3FZ-On"
      },
      "source": [
        "### データの取得\n",
        "\n",
        "まず、データセットをダウンロードします。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "p9kxxgzvzlyz",
        "colab": {}
      },
      "source": [
        "dataset_path = keras.utils.get_file(\"auto-mpg.data\", \"https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data\")\n",
        "dataset_path"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "nslsRLh7Zss4"
      },
      "source": [
        "pandasを使ってデータをインポートします。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "CiX2FI4gZtTt",
        "colab": {}
      },
      "source": [
        "column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',\n",
        "                'Acceleration', 'Model Year', 'Origin'] \n",
        "raw_dataset = pd.read_csv(dataset_path, names=column_names,\n",
        "                      na_values = \"?\", comment='\\t',\n",
        "                      sep=\" \", skipinitialspace=True)\n",
        "\n",
        "dataset = raw_dataset.copy()\n",
        "dataset.tail()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "3MWuJTKEDM-f"
      },
      "source": [
        "### データのクレンジング\n",
        "\n",
        "このデータには、いくつか欠損値があります。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "JEJHhN65a2VV",
        "colab": {}
      },
      "source": [
        "dataset.isna().sum()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "9UPN0KBHa_WI"
      },
      "source": [
        "この最初のチュートリアルでは簡単化のためこれらの行を削除します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "4ZUDosChC1UN",
        "colab": {}
      },
      "source": [
        "dataset = dataset.dropna()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "8XKitwaH4v8h"
      },
      "source": [
        "`\"Origin\"`の列は数値ではなくカテゴリーです。このため、ワンホットエンコーディングを行います。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "gWNTD2QjBWFJ",
        "colab": {}
      },
      "source": [
        "origin = dataset.pop('Origin')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ulXz4J7PAUzk",
        "colab": {}
      },
      "source": [
        "dataset['USA'] = (origin == 1)*1.0\n",
        "dataset['Europe'] = (origin == 2)*1.0\n",
        "dataset['Japan'] = (origin == 3)*1.0\n",
        "dataset.tail()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Cuym4yvk76vU"
      },
      "source": [
        "### データを訓練用セットとテスト用セットに分割\n",
        "\n",
        "データセットを訓練用セットとテスト用セットに分割しましょう。\n",
        "\n",
        "テスト用データセットは、作成したモデルの最終評価に使用します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "qn-IGhUE7_1H",
        "colab": {}
      },
      "source": [
        "train_dataset = dataset.sample(frac=0.8,random_state=0)\n",
        "test_dataset = dataset.drop(train_dataset.index)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "J4ubs136WLNp"
      },
      "source": [
        "### データの観察\n",
        "\n",
        "訓練用セットのいくつかの列の組み合わせの同時分布を見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "oRKO_x8gWKv-",
        "colab": {}
      },
      "source": [
        "sns.pairplot(train_dataset[[\"MPG\", \"Cylinders\", \"Displacement\", \"Weight\"]], diag_kind=\"kde\")"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "gavKO_6DWRMP"
      },
      "source": [
        "全体の統計値も見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "yi2FzC3T21jR",
        "colab": {}
      },
      "source": [
        "train_stats = train_dataset.describe()\n",
        "train_stats.pop(\"MPG\")\n",
        "train_stats = train_stats.transpose()\n",
        "train_stats"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Db7Auq1yXUvh"
      },
      "source": [
        "### ラベルと特徴量の分離\n",
        "\n",
        "ラベル、すなわち目的変数を特徴量から切り離しましょう。このラベルは、モデルに予測させたい数量です。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "t2sluJdCW7jN",
        "colab": {}
      },
      "source": [
        "train_labels = train_dataset.pop('MPG')\n",
        "test_labels = test_dataset.pop('MPG')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "mRklxK5s388r"
      },
      "source": [
        "### データの正規化\n",
        "\n",
        "上の`train_stats`のブロックをもう一度見て、それぞれの特徴量の範囲がどれほど違っているかに注目してください。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "-ywmerQ6dSox"
      },
      "source": [
        "スケールや値の範囲が異なる特徴量を正規化するのはよい習慣です。特徴量の正規化なしでもモデルは収束する**かもしれませんが**、モデルの訓練はより難しくなり、結果として得られたモデルも入力で使われる単位に依存することになります。\n",
        "\n",
        "注：（正規化に使用する）統計量は意図的に訓練用データセットだけを使って算出していますが、これらはテスト用データセットの正規化にも使うことになります。テスト用のデータセットを、モデルの訓練に使用した分布とおなじ分布に射影する必要があるのです。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "JlC5ooJrgjQF",
        "colab": {}
      },
      "source": [
        "def norm(x):\n",
        "  return (x - train_stats['mean']) / train_stats['std']\n",
        "normed_train_data = norm(train_dataset)\n",
        "normed_test_data = norm(test_dataset)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "BuiClDk45eS4"
      },
      "source": [
        "この正規化したデータを使ってモデルを訓練することになります。\n",
        "\n",
        "注意：ここで入力の正規化に使った統計量（平均と標準偏差）は、さきほど実施したワンホットエンコーディングとともに、モデルに供給するほかのどんなデータにも適用する必要があります。テスト用データセットだけでなく、モデルをプロダクション環境で使用する際の生のデータについても同様です。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "SmjdzxKzEu1-"
      },
      "source": [
        "## モデル"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "6SWtkIjhrZwa"
      },
      "source": [
        "### モデルの構築\n",
        "\n",
        "それではモデルを構築しましょう。ここでは、2つの全結合の隠れ層と、1つの連続値を返す出力層からなる、`Sequential`モデルを使います。モデルを構築するステップは`build_model`という1つの関数の中に組み込みます。あとから2つ目のモデルを構築するためです。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "c26juK7ZG8j-",
        "colab": {}
      },
      "source": [
        "def build_model():\n",
        "  model = keras.Sequential([\n",
        "    layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),\n",
        "    layers.Dense(64, activation='relu'),\n",
        "    layers.Dense(1)\n",
        "  ])\n",
        "\n",
        "  optimizer = tf.keras.optimizers.RMSprop(0.001)\n",
        "\n",
        "  model.compile(loss='mse',\n",
        "                optimizer=optimizer,\n",
        "                metrics=['mae', 'mse'])\n",
        "  return model"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "cGbPb-PHGbhs",
        "colab": {}
      },
      "source": [
        "model = build_model()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Sj49Og4YGULr"
      },
      "source": [
        "### モデルの検証\n",
        "\n",
        "`.summary`メソッドを使って、モデルの簡単な説明を表示します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ReAD0n6MsFK-",
        "colab": {}
      },
      "source": [
        "model.summary()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Vt6W50qGsJAL"
      },
      "source": [
        "では、モデルを試してみましょう。訓練用データのうち`10`個のサンプルからなるバッチを取り出し、それを使って`model.predict`メソッドを呼び出します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "-d-gBaVtGTSC",
        "colab": {}
      },
      "source": [
        "example_batch = normed_train_data[:10]\n",
        "example_result = model.predict(example_batch)\n",
        "example_result"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "QlM8KrSOsaYo"
      },
      "source": [
        "うまく動作しているようです。予定どおりの型と形状の出力が得られています。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "0-qWCsh6DlyH"
      },
      "source": [
        "### モデルの訓練\n",
        "\n",
        "モデルを1000エポック訓練し、訓練と検証の正解率を`history`オブジェクトに記録します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "sD7qHCmNIOY0",
        "colab": {}
      },
      "source": [
        "# エポックが終わるごとにドットを一つ出力することで進捗を表示\n",
        "class PrintDot(keras.callbacks.Callback):\n",
        "  def on_epoch_end(self, epoch, logs):\n",
        "    if epoch % 100 == 0: print('')\n",
        "    print('.', end='')\n",
        "\n",
        "EPOCHS = 1000\n",
        "\n",
        "history = model.fit(\n",
        "  normed_train_data, train_labels,\n",
        "  epochs=EPOCHS, validation_split = 0.2, verbose=0,\n",
        "  callbacks=[PrintDot()])"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "tQm3pc0FYPQB"
      },
      "source": [
        "`history`オブジェクトに保存された数値を使ってモデルの訓練の様子を可視化します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "4Xj91b-dymEy",
        "colab": {}
      },
      "source": [
        "hist = pd.DataFrame(history.history)\n",
        "hist['epoch'] = history.epoch\n",
        "hist.tail()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "B6XriGbVPh2t",
        "colab": {}
      },
      "source": [
        "def plot_history(history):\n",
        "  hist = pd.DataFrame(history.history)\n",
        "  hist['epoch'] = history.epoch\n",
        "  \n",
        "  plt.figure()\n",
        "  plt.xlabel('Epoch')\n",
        "  plt.ylabel('Mean Abs Error [MPG]')\n",
        "  plt.plot(hist['epoch'], hist['mae'],\n",
        "           label='Train Error')\n",
        "  plt.plot(hist['epoch'], hist['val_mae'],\n",
        "           label = 'Val Error')\n",
        "  plt.ylim([0,5])\n",
        "  plt.legend()\n",
        "  \n",
        "  plt.figure()\n",
        "  plt.xlabel('Epoch')\n",
        "  plt.ylabel('Mean Square Error [$MPG^2$]')\n",
        "  plt.plot(hist['epoch'], hist['mse'],\n",
        "           label='Train Error')\n",
        "  plt.plot(hist['epoch'], hist['val_mse'],\n",
        "           label = 'Val Error')\n",
        "  plt.ylim([0,20])\n",
        "  plt.legend()\n",
        "  plt.show()\n",
        "\n",
        "\n",
        "plot_history(history)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "AqsuANc11FYv"
      },
      "source": [
        "このグラフを見ると、検証エラーは100エポックを過ぎたあたりで改善が見られなくなり、むしろ悪化しているようです。検証スコアの改善が見られなくなったら自動的に訓練を停止するように、`model.fit`メソッド呼び出しを変更します。ここでは、エポック毎に訓練状態をチェックする*EarlyStopping*コールバックを使用します。設定したエポック数の間に改善が見られない場合、訓練を自動的に停止します。\n",
        "\n",
        "このコールバックについての詳細は[ここ](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/EarlyStopping)を参照ください。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "fdMZuhUgzMZ4",
        "colab": {}
      },
      "source": [
        "model = build_model()\n",
        "\n",
        "# patience は改善が見られるかを監視するエポック数を表すパラメーター\n",
        "early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)\n",
        "\n",
        "history = model.fit(normed_train_data, train_labels, epochs=EPOCHS,\n",
        "                    validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])\n",
        "\n",
        "plot_history(history)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "3St8-DmrX8P4"
      },
      "source": [
        "検証用データセットでのグラフを見ると、平均誤差は+/- 2 MPG（マイル/ガロン）前後です。これはよい精度でしょうか？その判断はおまかせします。\n",
        "\n",
        "モデルの訓練に使用していない**テスト用**データセットを使って、モデルがどれくらい汎化できているか見てみましょう。これによって、モデルが実際の現場でどれくらい正確に予測できるかがわかります。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "jl_yNr5n1kms",
        "colab": {}
      },
      "source": [
        "loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)\n",
        "\n",
        "print(\"Testing set Mean Abs Error: {:5.2f} MPG\".format(mae))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ft603OzXuEZC"
      },
      "source": [
        "### モデルを使った予測\n",
        "\n",
        "最後に、テストデータを使ってMPG値を予測します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Xe7RXH3N3CWU",
        "colab": {}
      },
      "source": [
        "test_predictions = model.predict(normed_test_data).flatten()\n",
        "\n",
        "plt.scatter(test_labels, test_predictions)\n",
        "plt.xlabel('True Values [MPG]')\n",
        "plt.ylabel('Predictions [MPG]')\n",
        "plt.axis('equal')\n",
        "plt.axis('square')\n",
        "plt.xlim([0,plt.xlim()[1]])\n",
        "plt.ylim([0,plt.ylim()[1]])\n",
        "_ = plt.plot([-100, 100], [-100, 100])\n"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "OrkHGKZcusUo"
      },
      "source": [
        "そこそこよい予測ができているように見えます。誤差の分布を見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "f-OHX4DiXd8x",
        "colab": {}
      },
      "source": [
        "error = test_predictions - test_labels\n",
        "plt.hist(error, bins = 25)\n",
        "plt.xlabel(\"Prediction Error [MPG]\")\n",
        "_ = plt.ylabel(\"Count\")"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "r9_kI6MHu1UU"
      },
      "source": [
        "とても正規分布には見えませんが、サンプル数が非常に小さいからだと考えられます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "vgGQuV-yqYZH"
      },
      "source": [
        "## 結論\n",
        "\n",
        "このノートブックでは、回帰問題を扱うためのテクニックをいくつか紹介しました。\n",
        "\n",
        "* 平均二乗誤差（MSE: Mean Squared Error）は回帰問題に使われる一般的な損失関数です（分類問題には異なる損失関数が使われます）。\n",
        "* 同様に、回帰問題に使われる評価指標も分類問題とは異なります。回帰問題の一般的な評価指標は平均絶対誤差（MAE: Mean Absolute Error）です。\n",
        "* 入力数値特徴量の範囲が異なっている場合、特徴量ごとにおなじ範囲に正規化するべきです。\n",
        "* 訓練用データが多くない場合、過学習を避けるために少ない隠れ層をもつ小さいネットワークを使うというのがよい方策の1つです。\n",
        "* Early Stoppingは過学習を防止するための便利な手法の一つです。"
      ]
    }
  ]
}